package com.msi.gui;

import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class FileWorker {

    protected static final Logger log = Logger.getLogger(FileWorker.class);

    private static File file;
    private static BufferedReader inputStream;
    private static FileInputStream fis;

    public static List<List<Integer>> extractNeighbourList(String fileName) {
        boolean rootIsConfigured = Logger.getRootLogger().getAllAppenders()
                .hasMoreElements();
        if (!rootIsConfigured)
            BasicConfigurator.configure();

        ArrayList<List<Integer>> neighbourMatrix = new ArrayList<List<Integer>>();

        openFile(fileName);
        return readGraph(fileName, neighbourMatrix);

    }

    public static List<List<Integer>> extractNeighbourList(File selectedFile) {
        boolean rootIsConfigured = Logger.getRootLogger().getAllAppenders()
                .hasMoreElements();
        if (!rootIsConfigured)
            BasicConfigurator.configure();
        List<List<Integer>> neighbourMatrix = new ArrayList<List<Integer>>();

        file = selectedFile;
        log.info("wtf");
        return readGraph(selectedFile.getName(), neighbourMatrix);

    }

    public static Map<Integer, Point2D> extractCoordinatesFromFile(
            File selectedFile) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            BufferedReader inputStream = new BufferedReader(
                    new InputStreamReader(fis));
            String line = "";
            boolean foundCoordinates = false;
            while ((line = inputStream.readLine()) != null) {
                if ("coordinates".equals(line.trim())) {
                    foundCoordinates = true;
                    break;
                }
            }
            Map<Integer, Point2D> map = new HashMap<Integer, Point2D>();
            if (foundCoordinates) {
                while ((line = inputStream.readLine()) != null) {
                    StringTokenizer tokenizer = new StringTokenizer(line);
                    log.debug("Wczytano linie, ilosc elementow: "
                            + tokenizer.countTokens());
                    if (tokenizer.countTokens() != 3) {
                        log.error("Probujemy odczytac wspolzedne ale jedna linijka wspolzednych zawiera zbyt malo danych, dlatego wczytanie wspolzednych jset anulowane");
                        continue;
                    }
                    int id = -1;
                    float longi = -1;
                    float latt = -1;
                    while (tokenizer.hasMoreTokens()) {
                        if (id == -1) {
                            id = Integer.parseInt(tokenizer.nextToken());
                        } else if (longi < 0) {
                            longi = Float.parseFloat(tokenizer.nextToken());
                        } else if (latt < 0) {
                            latt = Float.parseFloat(tokenizer.nextToken());
                            map.put(id, new Point2D.Double(longi, latt));
                        }

                    }
                }
                return map;
            }
            return null;

        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(FileWorker.class.getName()).log(
                    Level.SEVERE, null, ex);
            return null;
        } finally {
            try {
                fis.close();
            } catch (IOException ex) {
                java.util.logging.Logger.getLogger(FileWorker.class.getName())
                        .log(Level.SEVERE, null, ex);
                return null;
            }

        }
    }

    private static List<List<Integer>> readGraph(String fileName,
            List<List<Integer>> neighbourMatrix) {
        try {
            long start = System.currentTimeMillis();
            log.debug("otwieranie strumieni");
            openDataInputStream();
            readGraphToList(neighbourMatrix);
            // drawNeighbourMatrix(neighbourMatrix);
            long stop = System.currentTimeMillis();
            log.info("wczytywania grafu z pliku do listy:" + (stop - start));

        } catch (FileNotFoundException e) {
            log.error("Nie udalo sie otworzyc strumienia na pliku: " + fileName);
            return null;
        } catch (IOException e) {
            log.error("cos sie zjebalo przy odczytywaniu pliku: " + fileName);
            e.printStackTrace();
            return null;
        }
        return neighbourMatrix;
    }

    private static void drawNeighbourMatrix(List<List> neighbourMatrix) {
        log.info("Wczytano maciez sasiedztwa:");
        for (int i = 0; i < neighbourMatrix.size(); ++i) {
            for (int j = 0; j < neighbourMatrix.get(i).size(); ++j)
                System.out.print(" '" + neighbourMatrix.get(i).get(j) + "'");
            System.out.println("");
        }
    }

    private static void readGraphToList(List<List<Integer>> neighbourMatrix)
            throws IOException {
        String line = "";
        while ((line = inputStream.readLine()) != null) {
            StringTokenizer tokenizer = new StringTokenizer(line);
            // log.debug("Wczytano linie, ilosc elementow: "+tokenizer.countTokens());
            List<Integer> list = new ArrayList<Integer>();
            if ("coordinates".equals(line.trim()) || line.isEmpty()) {
                return;
            }
            while (tokenizer.hasMoreTokens()) {
                list.add(Integer.parseInt(tokenizer.nextToken()));
            }
            neighbourMatrix.add(list);
        }
    }

    private static void openDataInputStream() throws FileNotFoundException {
        fis = new FileInputStream(file);
        inputStream = new BufferedReader(new InputStreamReader(fis));
    }

    private static void openFile(String fileName) {
        file = new File(fileName);
    }

}
